

#ifndef _CELL_DECOMPOSITION_H_
#define _CELL_DECOMPOSITION_H_

// #include "common/cgal_def.h"
#include "bcd_decomposer.h"

#include <opencv2/opencv.hpp>

namespace global_path_planner
{
    namespace ccpp
    {

        class CellDecomposer
        {
        public:
            explicit CellDecomposer(std::shared_ptr<Polygon2D>& poly2d);

            virtual ~CellDecomposer();

            // 创建std::vector<PolygonWithHoles>几何模型
            std::vector<PolygonWithHoles> CreatePolygonWithHoles(std::vector<std::vector<cv::Point>> polys);

            // 分解多边形生成单个清扫轮廓
            std::vector<Polygon_2> DecomposePolygons(std::vector<PolygonWithHoles> &pwhs, cv::Mat& img);

            // bcd分解cell
            bool computeBestBCDFromPolygonWithHoles(const PolygonWithHoles &pwh,
                                                    std::vector<Polygon_2> *bcd_polygons);

            // tcd分解cell
            bool computeBestTCDFromPolygonWithHoles(const PolygonWithHoles &pwh,
                                                    std::vector<Polygon_2> *trap_polygons);

            // 多边形最长边作为最佳清扫方向
            Direction_2 findBestDirForSweep(const Polygon_2 &cell);

            // 最长边作为最佳的分解单元
            Direction_2 findBestDirForDecomposer(const PolygonWithHoles &pwh);

            // 获取最小外接矩形的边
            std::tuple<cv::Point2f, cv::Point2f, double> getlongestEdge(Polygon_2& poly);

            // 针对多边形两条边之间的夹角过小，重新投影坐标
            Polygon_2 CorrectPolygon(Polygon_2& origin_poly);

            // 分解cell类型
            enum DecompositionType
            {
                kBCD = 0, // Boustrophedon.
                kTCD      // Trapezoidal.
            };

            inline bool checkDecompositionTypeValid(const int type)
            {
                return (type == DecompositionType::kBCD) || (type == DecompositionType::kTCD);
            }

            inline std::string getDecompositionTypeName(const DecompositionType &type)
            {
                switch (type)
                {
                case DecompositionType::kBCD:
                    return "Boustrophedon Cell Decomposition";
                case DecompositionType::kTCD:
                    return "Trapezoidal Cell Decomposition";
                default:
                    return "Unknown!";
                }
            }

            /**
             * @brief 调试用 - 把多边形画在图片上
             */
            void DrawPolygonOnMap(const Polygon_2& polygon, const cv::Mat& cv_map, const cv::Scalar& color) const;

        private:
            
            // 垂直当前边的方向
            std::vector<Direction_2> findPerpEdgeDirections(const PolygonWithHoles &pwh);
            
            // 获取所有边的方向
            std::vector<Direction_2> findAllEdgeDirections(const PolygonWithHoles &pwh);
            
            // 移除多边形非相邻边有交点
            std::pair<bool, PolygonWithHoles> removeEdgesMoreThanPoints(PolygonWithHoles &pwh);

        private:
            std::shared_ptr<Polygon2D> __polygon2d_Ptr;
            std::shared_ptr<BcdDecomposer> __bcd_Decomp_Ptr;
            // 调试分解cell
            bool __debug_Cell;
            // 轮廓区域面积阈值
            float __min_Polygon_Area;
        };

    } // namespace ccpp
} // namespace global_path_planner

#endif // _CELL_DECOMPOSITION_H_